/*****************************
*   brA Item Extractor
*   Autor: Shiraz
*	Data: 21/02/2013
******************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <mysql/mysql.h>

#define TXTCOLOR(x) (SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), x))
#define EOL "\n"

#define EXT_FILE_NAME "idnum2itemdisplaynametable.txt"
#define OUT_FILE_NAME "item_db.sql"

MYSQL *mysql;
MYSQL_RES *result;
MYSQL_ROW rows;

enum txt_colors {
	DEFAULT = 15,
	GREEN = 47,
	YELLOW = 14,
	RED = 12,
	PINK = 13,
	WHITE = 7,
	LIGHT_GREEN = 10
};

struct item_data {
	char name[1024];
};

struct configuration {
	char host[1024], user[1024], password[1024], database[1024];
};

static struct item_data item[0x8000];
struct configuration config; 

void show_message(int color, const char *msg, ...);
void abort_system(void);
int explode(char ***arr_ptr, char *str, char delimiter);
char *escape_str(char *str);
void load_itemdb(void);

int main(void)
{
	char line[1024];
	FILE *fp, *fp2;
	int c;

	show_message(GREEN, "                                                                               "EOL);
	show_message(GREEN, "                 _           ___  _   _                                        "EOL);
	show_message(GREEN, "                | |         / _ \\| | | |                                       "EOL);
	show_message(GREEN, "                | |__  _ __/ /_\\ \\ |_| |__   ___ _ __    _ _                   "EOL);
	show_message(GREEN, "                | '_ \\| '__|  _  | __| '_ \\ / _ \\ '_ \\ / _` |                  "EOL);
	show_message(GREEN, "                | |_) | |  | | | | |_| | | |  __/ | | | (_| |                  "EOL);
	show_message(GREEN, "                |_.__/|_|  \\_| |_/\\__|_| |_|\\___|_| |_|\\__,_|                  "EOL);
	show_message(GREEN, "                                                                               "EOL);
	show_message(GREEN, "                      Project brAthena (c) 2008 - 2013                         "EOL);
	show_message(GREEN, "                              www.brathena.org                                 "EOL);
	show_message(GREEN, "                                                                               "EOL EOL);
	
	if(!(fp = fopen(EXT_FILE_NAME, "r"))) {
		show_message(RED, "File not found: %s. stopping..."EOL, EXT_FILE_NAME);
		abort_system();
	}
	
	load_itemdb();
	show_message(YELLOW, "Extracting items.."EOL);
	
	fp2 = fopen(OUT_FILE_NAME, "w+");

	while(fgets(line, sizeof(line), fp) != NULL) {
		line[strlen(line)-1] = '\0';
		char **rows, *str = line;

		if((line[0] == '/' && line[1] == '/') || line[0] == '\n' || strlen(str) < 2)
			continue;

		explode(&rows, str, '#');
		
		if(strlen(item[atoi(rows[0])].name))
			continue;
		
		fprintf(fp2, 
		"REPLACE INTO item_db VALUES(%d,'%s','%s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0xFFFFFFFF,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'{}','{}','{}');"EOL,
		atoi(rows[0]), escape_str(rows[1]), escape_str(rows[1]));
		c++;
	}
	
	show_message(LIGHT_GREEN, "Extraction completed, items extracted: %d"EOL, c);
	
	fclose(fp);
	fclose(fp2);
	abort_system();
}

void load_itemdb(void)
{
	char line[1024];
	int fields;
	FILE *fp;
	
	memset(item, 0, sizeof(item));

	if(!(fp = fopen("config.ini", "r"))) {
		show_message(RED, "File not found: %s. stopping..."EOL, "config.ini");
		abort_system();
	}
	
	while(fgets(line, sizeof(line), fp)) {
		line[strlen(line)-1] = '\0';
		char **rows, *str = line;

		if(strstr(line, "[") || strstr(line, ";"))
			continue;
		
		explode(&rows, str, '=');
		
		if(!strcmp(rows[0], "host"))
			strncpy(config.host, rows[1], sizeof(config.host));
		else if(!strcmp(rows[0], "user"))
			strncpy(config.user, rows[1], sizeof(config.user));
		else if(!strcmp(rows[0], "password"))
			strncpy(config.password, rows[1], sizeof(config.password));
		else if(!strcmp(rows[0], "database"))
			strncpy(config.database, rows[1], sizeof(config.database));
	}
	
	mysql = mysql_init(NULL);

	if(!(mysql_real_connect(mysql, config.host, config.user, config.password, config.database, 0, NULL, 0))) {
		show_message(RED, "An error occurred in connection with the MySQL: %s"EOL, mysql_error(mysql));
		abort_system();
	}
	
	show_message(WHITE, "Connection to MySQL: OK"EOL);
	
	exec_mysql_query("SELECT * FROM `item_db`");
	result = mysql_store_result(mysql);
	fields = mysql_num_fields(result);
	
	while((rows = mysql_fetch_row(result))) {
		strncpy(item[atoi(rows[0])].name, rows[1], sizeof((*item).name));
	}
	
}

int exec_mysql_query(const char* query)
{
	if(mysql_query(mysql, query)) {
		show_message(RED, "An error occurred during query: %s"EOL, mysql_error(mysql));
		abort_system();
	}

	return 0;
}

void show_message(int color, const char *msg, ...)
{
	TXTCOLOR(color);
	va_list args;

	va_start(args, msg);
	vfprintf(stdout, msg, args);
	TXTCOLOR(DEFAULT);
}

void abort_system(void)
{
	system("PAUSE");
	exit(0);
}

int explode(char ***arr_ptr, char *str, char delimiter)
{
	char *src = str, *end, *dst;
	char **arr;
	int size = 1, i;

	while((end = strchr(src, delimiter)) != NULL) {
		++size;
		src = end + 1;
	}

	arr = malloc(size * sizeof(char *) + (strlen(str) + 1) * sizeof(char));

	src = str;
	dst = (char *) arr + size * sizeof(char *);
	for(i = 0; i < size; ++i) {
		if ((end = strchr(src, delimiter)) == NULL)
			end = src + strlen(src);
		arr[i] = dst;
		strncpy(dst, src, end - src);
		dst[end - src] = '\0';
		dst += end - src + 1;
		src = end + 1;
	}
	*arr_ptr = arr;

	return size;
}

char *escape_str(char *str)
{
    char *new_str;
    char *source, *target;
    char *end;
    int new_length;
    int length = strlen(str);

    if(length == 0) {
        char *p = (char *) malloc(1);
        if (p == NULL) {
            return p;
        }
        p[0] = 0;
        return p;
    }

    new_str = (char *) malloc(2 * length + 1);
    if(new_str == NULL) {
        return new_str;
    }
    source = str;
    end = source + length;
    target = new_str;
    
    while(source < end) {
        switch(*source) {
            case '\0':
                *target++ = '\\';
                *target++ = '0';
                break;
            case '\'':
            case '\"':
            case '\\':
                *target++ = '\\';
            default:
                *target++ = *source;
                break;
        }
        source++;
    }
    
    *target = 0;
    new_length = target - new_str;
    new_str = (char *) realloc(new_str, new_length + 1);
    return new_str;
}
